<template>
  <div
    class="chart-box"
    style="width: 100%; height: 100%"
    :style="{ backgroundColor: widgetOptions.setup.backgroundColor }"
  >
    <div v-if="!chartStatus" ref="chartRef" style="width: 100%; height: 100%"></div>
    <ChartEmpty v-if="chartStatus" :chartStatus="chartStatus" />
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import * as echarts from 'echarts'
import { mapper } from '../constants'
import { useTools } from '../../hooks/useTools'
import { useWidgetTools } from '../../hooks/useWidgetTools'
import { useSignalView } from '../../hooks/useSignalView'
import ChartEmpty from '../../components/chartEmpty.vue'

// 接收父组件传入的值
const props = defineProps({
  widgetOptions: {
    type: Object as PropType<Record<string, any>>, // 或更具体的类型
    required: true
  },
  isPreview: {
    type: Boolean,
    default: false
  }
})

const chartRef = ref<HTMLDivElement | null>(null)
let myChart: echarts.ECharts | null = null
const chartData = ref<any>(null)

const { renderErrorBar, renderHistogram } = useWidgetTools()
const { toRgba } = useTools()
const mockDataUrl = '/mockdata/realtime/splAStatistics.json'

const initChart = () => {
  if (chartRef.value) {
    // 初始化实例
    myChart = echarts.init(chartRef.value)
  }
}

// 更新配置
const updateOptions = () => {
  if (!chartData.value) return
  const { signalName, startTime, duration, value, extra } = chartData.value
  const signalLabel = mapper[signalName] || ''

  const series: any[] = []
  const { hist, avg, se, median, min, max, percentile25, percentile75 } = value
  series.push({
    name: 'mean',
    type: 'bar',
    barWidth: '30%',
    xAxisIndex: 0,
    yAxisIndex: 0,
    data: [avg],
    label: {
      show: true,
      position: 'inside',
      color: props.widgetOptions.setup.barLabelFontColor,
      fontSize: props.widgetOptions.setup.barLabelFontSize
    },
    itemStyle: {
      color: props.widgetOptions.setup.barColor
    }
  })
  series.push({
    name: 'standard error',
    type: 'custom',
    itemStyle: {
      borderWidth: 1.5,
      color: 'red'
    },
    xAxisIndex: 0,
    yAxisIndex: 0,
    data: [[startTime, avg - se, avg + se]],
    renderItem: renderErrorBar,
    encode: { tooltip: [1, 2] },
    z: 100
  })
  series.push({
    name: 'boxplot',
    type: 'boxplot',
    xAxisIndex: 1,
    yAxisIndex: 1,
    itemStyle: {
      color: props.widgetOptions.setup.boxplotColor
    },
    data: [[min, percentile25, median, percentile75, max]]
  })
  const histData = hist.map((p) => [...p, p[0].toFixed(2) + '-' + p[1].toFixed(2)])
  series.push({
    name: 'histogram',
    data: histData,
    type: 'custom',
    renderItem: renderHistogram,
    encode: {
      label: [3, 2]
    },
    xAxisIndex: 2,
    yAxisIndex: 2,
    label: {
      show: true,
      position: 'right',
      formatter: function (params) {
        const { data } = params
        return '范围：' + data[3] + '  数量：' + data[2]
      }
    },
    tooltip: {
      show: false
    },
    itemStyle: {
      color: props.widgetOptions.setup.rectColor
    }
  })

  const yMin = +Math.floor(min).toFixed(0)
  const yMax = +Math.ceil(max).toFixed(0)
  const xMax = Math.max(...hist.map((p) => p[2]))
  const xData = [startTime]
  const option = {
    title: {
      text: `最近${duration}秒${signalLabel}`,
      subtext: `开始时间：${startTime}`,
      left: 'center',
      textStyle: {
        color: props.widgetOptions.setup.titleColor,
        fontSize: props.widgetOptions.setup.titleFontSize
      },
      subtextStyle: {
        color: props.widgetOptions.setup.subtitleColor,
        fontSize: props.widgetOptions.setup.subtitleFontSize
      }
    },
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      top: '50',
      itemStyle: {
        color: props.widgetOptions.setup.legendColor
      },
      textStyle: {
        color: props.widgetOptions.setup.legendFontColor,
        fontSize: props.widgetOptions.setup.legendFontSize
      }
    },
    grid: [
      {
        top: '80',
        left: '5%',
        right: '75%'
      },
      {
        top: '80',
        left: '25%',
        right: '50%'
      },
      {
        top: '80',
        left: '50%',
        right: '25%'
      }
    ],
    xAxis: [
      {
        type: 'category',
        gridIndex: 0,
        data: xData,
        axisLine: {
          show: true,
          lineStyle: {
            color: props.widgetOptions.setup.xLineColor
          }
        },
        axisLabel: {
          color: props.widgetOptions.setup.xFontColor,
          fontSize: props.widgetOptions.setup.xFontSize
        }
      },
      {
        type: 'category',
        gridIndex: 1,
        data: xData,
        axisLine: {
          lineStyle: {
            color: props.widgetOptions.setup.xLineColor
          }
        },
        axisLabel: {
          color: props.widgetOptions.setup.xFontColor,
          fontSize: props.widgetOptions.setup.xFontSize
        }
      },
      {
        type: 'value',
        gridIndex: 2,
        max: xMax,
        splitLine: { show: false },
        axisLine: {
          lineStyle: {
            color: props.widgetOptions.setup.xLineColor
          }
        },
        axisLabel: {
          color: props.widgetOptions.setup.xFontColor,
          fontSize: props.widgetOptions.setup.xFontSize
        }
      }
    ],
    yAxis: [
      {
        type: 'value',
        gridIndex: 0,
        min: yMin,
        max: yMax,
        splitNumber: 5,
        axisLabel: {
          color: props.widgetOptions.setup.yFontColor,
          fontSize: props.widgetOptions.setup.yFontSize
        },
        splitLine: {
          show: props.widgetOptions.setup.ySplitLine,
          lineStyle: {
            color: 'rgba(255,255,255,0.2)'
          }
        }
      },
      {
        type: 'value',
        gridIndex: 1,
        min: yMin,
        max: yMax,
        axisTick: { show: false },
        axisLabel: { show: false },
        axisLine: { show: false },
        splitNumber: 5
      },
      {
        scale: true,
        gridIndex: 2,
        min: yMin,
        max: yMax,
        axisTick: { show: false },
        axisLabel: { show: false },
        axisLine: { show: false },
        splitNumber: 5
      }
    ],
    series: series
  }

  myChart?.setOption(option)
  myChart?.resize()
}

const resolveData = (data: any) => {
  if (data && data.msgPack) {
    chartStatus.value = ''
    chartData.value = data.msgPack
    updateOptions()
  } else {
    chartStatus.value = 'noData'
    chartData.value = null
  }
}

const resolveMockData = (data: any) => {
  chartData.value = data
  updateOptions()
}

const { chartStatus, refreshData } = useSignalView(
  props.widgetOptions,
  props.isPreview,
  mockDataUrl,
  resolveData,
  resolveMockData
)

onMounted(() => {
  initChart()
  refreshData()
})

// 如果父组件传入的 props.value 改变，需要更新折线图颜色等
watch(
  () => props.widgetOptions,
  () => {
    if (myChart) {
      updateOptions()
    }
  },
  { immediate: true, deep: true }
)

onBeforeUnmount(() => {
  if (myChart) {
    myChart.dispose()
  }
})
</script>

<style scoped></style>
